;; package mirror
(setq package-archives '(("gnu"   . "http://elpa.emacs-china.org/gnu/")
                         ("melpa" . "http://elpa.emacs-china.org/melpa/")))

;; add to load-path
;; for manually installed packages
;; to require('package)
(add-to-list 'load-path
	     (expand-file-name "~/.emacs.d/lisp"))

;;;;; manually require packages
;; column-marker
(require 'column-marker)
(add-hook 'prog-mode-hook
	  (lambda () (interactive) (column-marker-1 80)))

;; packages initialize
(package-initialize)

;; use-package & auto-pacakge-update
(if (not (package-installed-p 'use-package))
    (progn
      (package-refresh-contents)
      (package-install 'use-package)))

(setq use-package-always-ensure t)
(eval-when-compile
  (require 'use-package))

(use-package auto-package-update
  :config
  (setq auto-package-update-delete-old-versions t)
  (setq auto-package-update-hide-results t)
  (auto-package-update-maybe))

;;;;; built-in functions
;; emacs
(use-package emacs
  :bind (("C-x c e" . eval-region)))

;;;;; installed packages
;; ivy, counsel
(use-package counsel)
(use-package ivy
  :bind (("C-s"		. swiper)
	 ("C-c C-r"	. ivy-resume)
	 ("<f6>"	. ivy-resume)
	 ("M-x"		. counsel-M-x)
	 ("C-x C-f"	. counsel-find-file)
	 ("<f1> f"	. counsel-describe-function)
	 ("<f1> v"	. counsel-describe-variable)
	 ("<f1> l"	. counsel-find-library)
	 ("<f2> i"	. counsel-info-lookup-symbol)
	 ("<f2> u"	. counsel-unicode-char)
	 ("C-c g"	. counsel-git)
	 ("C-c j"	. counsel-git-grep)
	 ("C-c k"	. counsel-ag)
	 ("C-x l"	. counsel-locate)
	 ("C-S-o"	. counsel-rhythmbox)
	 :map minibuffer-local-map
	 ("C-r"		. counsel-minibuffer-history))
  :config
  (setq ivy-use-virtual-buffers t)
  (setq ivy-use-selectable-prompt t)
  (setq enable-recursive-minibuffers t)
  (ivy-mode 1))

;; company-mode
(use-package company
  :hook (after-init . global-company-mode))

;; neotree
(use-package neotree
  :config
  (setq neo-theme 'arrow)
  (setq neo-smart-open t)
  (setq projectile-switch-project-action 'neotree-projectile-action)
  :bind ("<f8>" . neotree-toggle))
					
;; projectile
(use-package projectile
  :config
  (projectile-mode +1)
  :bind-keymap
  (("s-p" . projectile-command-map)
   ("C-c p" . projectile-command-map)))

;; neotree & projectile
(defun neotree-project-dir ()
  "Open NeoTree using the git root."
  (interactive)
  (let ((project-dir (projectile-project-root))
        (file-name (buffer-file-name)))
    (neotree-toggle)
    (if project-dir
        (if (neo-global-window-exists-p)
            (progn
              (Neotree-Dir Project-Dir)
              (Neotree-Find file-name)))
      (message "Could not find git project root."))))

;; ace-window
(use-package ace-window
  :bind ("C-x o" . ace-window)
  :config
;;   (setq aw-dispatch-always t)
  (setq aw-background nil))

;; ace-jump
(use-package ace-jump-mode
  :bind (("C-x j" . ace-jump-mode)
	 ("C-x ESC j" . ace-jump-mode-pop-mark))
  :config
  (ace-jump-mode-enable-mark-sync))

;; ace-link
(use-package ace-link
  :bind (
	 ("C-x c l" . ace-link-addr)
	 :map org-mode-map
         ("C-x c l" . ace-link-org)
         :map gnus-summary-mode-map
         ("C-x c l" . ace-link-gnus)
         :map gnus-article-mode-map
         ("C-x c l" . ace-link-gnus))
  :config
  (ace-link-setup-default))

;; anzu
(use-package anzu
  :bind (("C-x /" . anzu-query-replace)
	 ("C-x ?" . anzu-query-replace-regexp))
  :config
  (anzu-mode +1))

;; bm
(use-package bm
  :demand t
  :init
  (setq bm-restore-repository-on-load t)
  :config
  (setq bm-cycle-all-buffers nil)
  (setq bm-repository-file "~/.emacs.d/bm-repository")
  (setq-default bm-buffer-persistence t)
  :hook ((kill-buffer . bm-buffer-save)
	 (kill-emacs . (lambda nil
			 (bm-buffer-save-all)
			 (bm-repository-save)))
	 (after-save . bm-buffer-save)
	 (find-file . bm-buffer-restore)
	 (after-revert . bm-buffer-restore)
	 (vc-before-checkin-hook . bm-buffer-save))
  :bind (("<f2>" . bm-next)
	 ("S-<f2>" . bm-previous)
	 ("C-<f2>" . bm-toggle))
  :custom
  (bm-highlight-style 'bm-highlight-only-fringe))

;; magit
(use-package magit
  :bind ("C-x g" . magit-status))

;; git-gutter
(use-package git-gutter
  :hook (ruby-mode . git-gutter-mode)
  :bind (("C-x v g" . git-gutter)
	 ("C-x v =" . git-gutter:popup-hunk)
	 ("C-x p" . git-gutter:previous-hunk)
	 ("C-x n" . git-gutter:next-hunk)
	 ("C-x v s" . git-gutter:stage-hunk)
	 ("C-x v r" . git-gutter:revert-hunk)
         ("C-x v SPC" . git-gutter:mark-hunk))
  :custom
  (git-gutter:window-width 2)
  (git-gutter:modified-sign "☁")
  (git-gutter:added-sign "☀")
  (git-gutter:deleted-sign "☂")
  :config
  (set-face-background 'git-gutter:modified "purple")
  (set-face-foreground 'git-gutter:added "green")
  (set-face-foreground 'git-gutter:deleted "red")
  (global-git-gutter-mode t)
  (git-gutter:linum-setup))

;; highlight-thing
(use-package highlight-thing
  :config
  (setq highlight-thing-all-visible-buffers-p t)
  (setq highlight-thing-ignore-list '("false" "true")))
;;   (global-highlight-thing-mode))

;; string-inflection
(use-package string-inflection
  :bind ("C-c f C-u" . string-inflection-all-cycle)
  :hook ((ruby-mode . (lambda ()
			(local-set-key (kbd "C-c f C-u") 'string-inflection-ruby-style-cycle)))
	 (java-mode . (lambda ()
			(local-set-key (kbd "C-c f C-u") 'string-inflection-java-style-cycle)))
	 (python-mode . (lambda ()
			  (local-set-key (kbd "C-c f C-u") 'string-inflection-python-style-cycle)))))

;; easy-kill
(use-package easy-kill
  :bind (("M-w" . easy-kill)
	 ("M-m" . easy-mark)))

;; browse-kill-ring
(use-package browse-kill-ring
  :bind ("M-y" . browse-kill-ring)
  :config
  (setq browse-kill-ring-highlight-current-entry t)
  (setq browse-kill-ring-highlight-inserted-item 'pulse))

;; focus
(use-package focus)
;;   :hook (prog-mode . focus-mode))
  
;; undo-tree
(use-package undo-tree
  :config
  (global-undo-tree-mode))

;; which-key
(use-package which-key
  :config
  (which-key-setup-side-window-right-bottom)
  (setq which-key-popup-type 'minibuffer)
  (setq which-key-paging-prefixes '("C-x"))
  (setq which-key-paging-key "<f5>")
  (which-key-mode))

;; rainbow-delimiters
(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))

;; multiple-cursors
(use-package multiple-cursors
  :bind (("C-S-c C-S-c" . mc/edit-lines)
	 ("C->" . mc/mark-next-like-this)
	 ("C-<" . mc/mark-previous-like-this)
	 ("C-c C-<" . mc/mark-all-like-this)))

;; yasnippet
(use-package yasnippet
  :config
  (setq yas-snippet-dirs
	(list (expand-file-name "~/.emacs.d/snippets")))
  (yas-global-mode 1))

;; yasnippet-snippets
(use-package yasnippet-snippets
  :config
  (setq yas-snippet-dirs (append yas-snippet-dirs (list yasnippet-snippets-dir))))

;; ;; auto-yasnippet
;; (use-package auto-yasnippet
;;   :bind (("H-w" . aya-create)
;; 	 ("H-y" . aya-expand)
;; 	 ("C-o" . aya-open-line)))

;; emmet, C-j
(use-package emmet-mode
  :hook ((sgml-mode . emmet-mode)
	 (css-mode . emmet-mode)
	 (emmet-mode . (lambda ()
			 (setq emmet-indent-after-insert nil)))))

;; indent-guide
(use-package indent-guide
  :config
  (indent-guide-global-mode))

;; smartparens
(use-package smartparens
  :config
  (require 'smartparens-config)
  :hook (prog-mode . smartparens-mode))

;; smart-mode-line
(use-package smart-mode-line
  :config
  (setq sml/theme 'dark)
  (setq sml/no-confirm-load-theme t))

;; emojify
(use-package emojify)
;;   :hook (after-init . global-emojify-mode))

;; markdown-mode
(use-package markdown-mode
  :commands (markdown-mode gfm-mode)
  :mode (("README\\.md\\'" . gfm-mode)
	 ("\\.md\\'" . markdown-mode)
	 ("\\.markdown\\'" . markdown-mode))
  :config
  (setq markdown-command "multimarkdown"))

;;;;;;;;;;;; language supports
;; lua-mode
(use-package lua-mode
  :mode ("\\.lua\\'" . lua-mode))

;; org-capture-templates
(setq org-capture-templates
      '(("t" "Todo"    entry (file+headline "~/.emacs.d/org/gtd.org" "Tasks")
         "* TODO %?\n %i\n %a")
        ("j" "Journal" entry (file+datetree "~/.emacs.d/org/journal.org")
         "* %?\nEntered on %U\n %i\n %a")
	("n" "Note"    entry (file+datetree "~/.emacs.d/org/note.org")
	 "* %?\nEntered on %U\n %i\n %a")))

;; org-brain
(use-package org-brain
  :config
  (setq org-id-track-globally t)
  (setq org-bran-path "~/.emacs.d/org-brain")
  (setq org-id-locations-file "~/.emacs.d/.org-id-locations")
  (push '("b" "Brain" plain (function org-brain-goto-end)
	  "* %i%?" :empty-lines 1)
	org-capture-templates)
  (setq org-brain-visualize-default-choices 'all)
  (setq org-brain-title-max-length 12))

;; org-publish
(use-package htmlize)
(use-package ox-rst)
(use-package ox-asciidoc)
(use-package adoc-mode
  :config
  (add-to-list 'auto-mode-alist (cons "\\.txt\\'" 'adoc-mode)))
(use-package org
;;   :hook
;;   (add-hook 'org-babel-after-execute-hook 'bh/display-inline-images 'append)
  
  :bind (("C-c c" . org-capture)
	 :map org-mode-map
	 ("C-c (" . org-mark-ring-goto))
  
  :config
  (setq org-startup-with-inline-images t)
  (if (string-version-lessp org-version "9.2")
	  (add-to-list 'org-structure-template-alist
	       (list "P"
		 (string-trim "
#+SETUPFILE: ~/.emacs.d/org-templates/wiki/level-1.org
#+STARTUP: showall
#+HTML_LINK_UP:
#+HTML_LINK_HOME:
#+DESCRIPTION:
#+KEYWORDS:
#+SUBTITLE:
#+TITLE:
#+DATE:")))
	(require 'org-tempo)
    (add-to-list 'org-structure-template-alist
	             '("P" . "#+SETUPFILE: ~/.emacs.d/org-templates/wiki/level-1.org
#+STARTUP: showall
#+HTML_LINK_UP:
#+HTML_LINK_HOME:
#+DESCRIPTION:
#+KEYWORDS:
#+SUBTITLE:
#+TITLE:
#+DATE:")))

  ;; Use fundamental mode when editing plantuml blocks with C-c '
  (add-to-list 'org-src-lang-modes '("plantuml" . fundamental))
  
  ;; <C-c C-c> to eval on 'org-mode'
  (setq org-confirm-babel-evaluate nil)
  (org-babel-do-load-languages 'org-babel-load-languages
			       '((emacs-lisp . t)
				 (ditaa . t)
				 (dot . t)
				 (R . t)
				 (python . t)
				 (ruby . t)
				 (gnuplot . t)
				 (clojure . t)
				 (shell . t)
				 (ledger . t)
				 (org . t)
				 (plantuml . t)
				 (latex . t)
				 (calc . t)
				 (C . t)))
  
  (setq org-publish-project-alist
	'(("blog-content"
	   :base-directory "~/.emacs.d/org-blog/org"
	   :base-extension "org"
	   :publishing-directory "~/.emacs.d/org-blog/publish"
	   :recursive t
	   :publishing-function org-html-publish-to-html
	   :headline-levels 4
	   :section-numbers t
	   :auto-preamble t
	   :auto-sitemap t
	   :sitemap-filename "sitemap.html"
	   :sitemap-title "Sitemap")
	  
	  ("blog-static"
	   :base-directory "~/.emacs.d/org-blog/org"
	   :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf"
	   :publishing-directory "~/.emacs.d/org-blog/publish"
	   :recursive t
	   :publishing-function org-publish-attachment)
	  
	  ("org-blog" :components ("blog-content" "blog-static"))
	  
	  ("wiki-content"
	   :base-directory "~/.emacs.d/org-wiki/org"
	   :base-extension "org"
	   :publishing-directory "~/.emacs.d/org-wiki/publish"
	   :recursive t
	   :publishing-function org-html-publish-to-html org-rst-publish-to-rst org-asciidoc-export-to-asciidoc
	   :headline-levels 4
	   :section-numbers t
	   :auto-preamble t
	   :auto-sitemap t
	   :sitemap-filename "sitemap.html"
	   :sitemap-title "Sitemap")
	  
	  ("wiki-static"
	   :base-directory "~/.emacs.d/org-wiki/org"
	   :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf"
	   :publishing-directory "~/.emacs.d/org-wiki/publish"
	   :recursive t
	   :publishing-function org-publish-attachment)
	  
	  ("org-wiki" :components ("wiki-content" "wiki-static"))))
  (setq org-default-notes-file "~/.emacs.d/org/default.org"))

;;;;; configs
;; autosave, backup
(setq backup-directory-alist
    `(("." . ,(concat user-emacs-directory "backups"))))
(setq auto-save-file-name-transforms
    `((".*" ,temporary-file-directory t)))

;; UTF-8 as default encoding
(set-language-environment "UTF-8")
(prefer-coding-system 'utf-8)

;; Truncate-lines, set default to no line wrap
(set-default 'truncate-lines t)
(global-set-key "\C-c$" 'toggle-truncate-lines)

;; tabs & spaces
(setq-default tab-width 4)
(setq tab-width 4)
(setq-default tab-always-indent t)

;; horizontal scrolling mouse events should actually scroll left and right.
(global-set-key (kbd "<mouse-6>") (lambda () (interactive)
				    (if truncate-lines (scroll-right 1))))
(global-set-key (kbd "<mouse-7>") (lambda () (interactive)
				    (if truncate-lines (scroll-left 1))))
;; gui menubar,   disable menubar
(menu-bar-mode -1)
;; gui toolbar,   disable toolbar
(tool-bar-mode -1)
;; gui scrollbar, disable scrollbar
(if (featurep 'scroll-bar)
    (scroll-bar-mode -1))

;; session management
(setq desktop-path '("~/.emacs.d/desktops"))
(desktop-save-mode 1)
(use-package session
  :hook (after-init . session-initialize)
  :config
  (add-to-list 'session-globals-exclude 'org-mark-ring))


;;;;; custom-set-variables
;; check init.el for the ids of safe themes
(custom-set-variables
 '(custom-safe-themes '("840db7f67ce92c39deb38f38fbc5a990b8f89b0f47b77b96d98e4bf400ee590a" "3c83b3676d796422704082049fc38b6966bcad960f896669dfc21a7a37a748fa" "8db4b03b9ae654d4a57804286eb3e332725c84d7cdab38463cb6b97d5762ad26" "628278136f88aa1a151bb2d6c8a86bf2b7631fbea5f0f76cba2a0079cd910f7d" "bb08c73af94ee74453c90422485b29e5643b73b05e8de029a6909af6a3fb3f58" "1b8d67b43ff1723960eb5e0cba512a2c7a2ad544ddb2533a90101fd1852b426e" "06f0b439b62164c6f8f84fdda32b62fb50b6d00e8b01c2208e55543a6337433a" default)))

;;;;; platforms
(message (concat ";;;;; Your emacs is running on: " (symbol-name system-type)))
(if (equal system-type 'darwin)
    (progn ;; OS X specially configs
      (setq org-plantuml-jar-path "~/.local/lib/java/plantuml.jar")
      (add-to-list 'default-frame-alist '(font . "DejaVu Sans Mono-10")))
  (if (equal system-type 'windows-nt)
      (progn ;; Windows specially configs
	(setq org-plantuml-jar-path (concat (getenv "EMACS_PATH") "/share/emacs/26.1/lisp/contrib/scripts/plantuml.jar"))
	(add-to-list 'default-frame-alist '(font . "DejaVu Sans Mono-10")))
    (if (or (equal system-type 'gnu/linux) (equal system-type 'cygwin))
	(progn ;; Linux specially configs
	  (setq org-plantuml-jar-path "/usr/share/emacs/26.1/lisp/contrib/scripts/plantuml.jar")
	  (add-to-list 'default-frame-alist '(font . "DejaVu Sans Mono-9"))))))
